package com.quan.upms.aspect;

import java.lang.reflect.Method;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.quan.base.common.utils.IpHelper;
import com.quan.sso.common.pojo.SSOUser;
import com.quan.sso.common.tools.UserHolder;
import com.quan.upms.annotation.RequiresPermissions;

@Component
@Aspect
public class AccessLogAspect {

	private static final Logger LOGGER = LoggerFactory.getLogger(AccessLogAspect.class);

	// 开始时间
	private long startTime = 0L;

	// 结束时间
	private long endTime = 0L;
	
	//排除不需要日志记录URI
	private static final String excludes = "((about$)|(login$)|(/wx))" ;

	@Before("execution(* *..controller..*.*(..))")
	public void doBeforeInServiceLayer(JoinPoint joinPoint) {
		startTime = System.currentTimeMillis();
	}

	@After("execution(* *..controller..*.*(..))")
	public void doAfterInServiceLayer(JoinPoint joinPoint) {
	}

	@Around("execution(* *..controller..*.*(..))")
	public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
		// 获取request
		RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
		ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) requestAttributes;
		HttpServletRequest request = servletRequestAttributes.getRequest();
		
		// 从注解中获取操作名称、获取响应结果
		Object result = pjp.proceed();
		if(!requestIsExclude(request)) {
			//当前登录用户信息
			SSOUser user = UserHolder.getUser();
			
			Signature signature = pjp.getSignature();
			MethodSignature methodSignature = (MethodSignature) signature;
			Method method = methodSignature.getMethod();

			//权限注解
			RequiresPermissions annotation = method.getAnnotation(RequiresPermissions.class);
			
			endTime = System.currentTimeMillis();
			LOGGER.info("用户:{}, 操作:{}, IP:{}, URI:{}, 耗时:{}(ms), UserAgent:{}",
					user != null ? user.getAccount() : "未登录",
					(annotation != null && !annotation.description().equals("") ? annotation.description() : "未注释"),
					IpHelper.getIpAddr(request),
					request.getRequestURI(),
					endTime - startTime,
					request.getHeader("User-Agent")
					);
		}
		
		
		
		return result;
	}

	private boolean requestIsExclude(HttpServletRequest request) {
		// 没有设定excludes是，所有经过filter的请求都需要被处理
		if (StringUtils.isEmpty(excludes)) {
			return false;
		}

		// 获取去除context path后的请求路径
		String contextPath = request.getContextPath();
		String uri = request.getRequestURI();
		uri = uri.substring(contextPath.length());

		Pattern p = Pattern.compile(excludes);
		Matcher m = p.matcher(uri);
		// 正则表达式匹配URI被排除，不需要拦截
		boolean isExcluded = m.find();
		if (isExcluded) {
			//LOGGER.debug("日志拦截==>该请求地址不需登录即可访问(但权限验证和操作日志记录拦截器无法获取当前用户 ): {}", uri);
		}

		return isExcluded;
	}
}
